package model.network.netty

import cn.hutool.core.util.IdUtil
import cn.hutool.json.JSONObject
import cn.hutool.json.JSONUtil
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.channel.socket.DatagramPacket
import io.netty.util.CharsetUtil
import model.db.Db
import model.dto.MessageSqlDTO
import model.enums.ApplyState
import model.enums.MsgContentItemType
import model.enums.NoticeType
import model.repository.ChannelMappingRepository
import model.repository.MessageRepository
import model.vo.*
import ui.home.HomeViewModel
import java.lang.reflect.Type

/**
 * @author wei kunJie
 * @date 2024/3/3 17:19:54
 */
class QuoteOfTheMomentClientHandler : SimpleChannelInboundHandler<DatagramPacket>() {
    private var homeViewModel: HomeViewModel? = null
    fun setHomeViewModel(viewModel: HomeViewModel) {
        homeViewModel = viewModel
    }

    private val gson = Gson()

    @Throws(Exception::class)
    override fun channelRead0(ctx: ChannelHandlerContext, msg: DatagramPacket) {
        val response = msg.content().toString(CharsetUtil.UTF_8)
        val jsonObject: JSONObject = JSONUtil.parseObj(response)
        println("服务器响应：$response")
        val data: JSONObject = jsonObject["data"] as JSONObject
        if (data["notices"] != null) {
            val notices = data["notices"] as Map<String, Any>
            handleNotices(notices, homeViewModel)//处理通知
        }
        if (data["messageVOList"] != null) {//接收消息
            val messageVOListJsonString: String = gson.toJson(data["messageVOList"])
            handleMessage(messageVOListJsonString, gson, homeViewModel)
        }
        if (data["ackMessageId"] != null) {//处理发送消息后的ack
            val ackMsgId = data["ackMessageId"] as Long
            handleMsgAck(ackMsgId, homeViewModel)
        }
    }
}

fun handleMsgAck(ackMsgId: Long, homeViewModel: HomeViewModel?) {
    //收到ack，持久化 消息，并删除 消息的“正在发送”状态
    if (MessageRepository.sendingMessageMap[ackMsgId.toString()] == null) return
    Db.saveMessage(MessageSqlDTO(MessageRepository.sendingMessageMap[ackMsgId.toString()]!!))
    MessageRepository.sendingMessageMap.remove(ackMsgId.toString())
}

fun handleMessage(messageVOListJsonString: String, gson: Gson, homeViewModel: HomeViewModel?) {
    val listType: Type = object : TypeToken<List<MessageVO?>?>() {}.type
    val messageVOList: List<MessageVO> = gson.fromJson(messageVOListJsonString, listType)
    messageVOList.forEach {
        val msgContentItems = it.contentItemList.reversed()
        val contentStringBuilder = StringBuilder()
        msgContentItems.forEach { contentItem ->
            if (contentItem.type == MsgContentItemType.text || contentItem.type == MsgContentItemType.url) {
                contentStringBuilder.append(contentItem.context)
            } else {
                contentStringBuilder.append("[${contentItem.type}]")
            }
        }
        val existMessageListItem = homeViewModel?.messageList?.find { isExistIt ->
            isExistIt.account == it.fromUserAccount && isExistIt.isGroup == it.isGroup
        }
        if (existMessageListItem == null) {//不存在，直接置顶
            val messageListItem = MessageListItem(
                id = it.id,
                account = it.fromUserAccount,
                headImage = it.fromUserAvatar,
                title = it.fromUserName,
                time = it.time,
                isGroup = it.isGroup,
                count = 1,
                msg = contentStringBuilder.toString(),
            )
            messageListItem.messageContentItems = listOf(
                MessageContentItem(
                    id = it.id,
                    userAccount = it.fromUserAccount,
                    userName = it.fromUserName,
                    userHeadImageUrl = it.fromUserAvatar,
                    content = contentStringBuilder.toString(),
                    time = it.time
                )
            )
            homeViewModel?.messageList?.add(0, messageListItem)
            Db.saveMsgList(messageListItem)//持久化
        } else {//存在
            //删除原来的
            val index = homeViewModel.messageList.indexOf(existMessageListItem)
            homeViewModel.messageList.remove(existMessageListItem)
            //修改
            if (homeViewModel.msgListItemSelectId.value != existMessageListItem.id) {
                existMessageListItem.count = existMessageListItem.count + 1
            }
            existMessageListItem.msg = contentStringBuilder.toString()
            existMessageListItem.messageContentItems = listOf(
                MessageContentItem(
                    id = it.id,
                    userAccount = it.fromUserAccount,
                    userName = it.fromUserName,
                    userHeadImageUrl = it.fromUserAvatar,
                    content = contentStringBuilder.toString(),
                    time = it.time
                )
            ) + existMessageListItem.messageContentItems
            //更新UI
            if (existMessageListItem.count == 1) {//如果原来未读是零，有新消息来就置顶
                homeViewModel.messageList.add(0, existMessageListItem)
            } else {//存在，并有之前的未读，不动位置，只加未读数
                homeViewModel.messageList.add(index, existMessageListItem)
            }
            Db.saveMsgList(existMessageListItem)//持久化
            //更新聊天框
            if (homeViewModel.msgListItemSelectId.value == existMessageListItem.id) {
                homeViewModel.messageContentItemList.add(0, existMessageListItem.messageContentItems[0])
            }
        }
        //保存消息
        Db.saveMessage(MessageSqlDTO(it))
        println("收到来自：${it.fromUserAccount} ${it.fromUserName} 的信息：")
        it.contentItemList.forEach { it1 ->
            println("type：${it1.type} context：${it1.context}")
        }
    }

}

fun handleNotices(notices: Map<String, Any>, homeViewModel: HomeViewModel?) {
    notices.forEach {
        if (it.key.endsWith(NoticeType.friendApply)) {
            //好友申请通知
            val noticeVOMap = it.value as Map<String, Any>
            val publishId = noticeVOMap["publishId"]
            val consumerId = noticeVOMap["consumerId"]
            val noticeType = noticeVOMap["noticeType"]
            val noticeVOData = noticeVOMap["data"] as Map<String, Any>
            val apply = noticeVOData["apply"] as Map<String, Any>
            val applyId = apply["id"]
            val applyActiveId = apply["activeId"]
            val applyPassiveId = apply["passiveId"]
            val applyAuthenticationInformation = apply["authenticationInformation"]
            val applyIsGroup = apply["isGroup"]
            val applyState = apply["state"]
            val activityUser = noticeVOData["activityUser"] as Map<String, Any>
            val account = activityUser["account"]
            val username = activityUser["username"]
            val avatar = activityUser["avatar"]
            val friendNotificationItem = FriendNotificationItem(
                id = (applyId).toString().toLong(),
                headImage = avatar as String,
                userName = username as String,
                content = "验证信息：${applyAuthenticationInformation}",
                applyState = applyState as String,
                time = "2024/4/17",
                friendAccount = account as String,
                noticeType = NoticeType.friendApply
            )
            //将通知保存本地
            Db.saveFriendNotice(friendNotificationItem)
            //将通知渲染
            homeViewModel?.friendNotificationItems?.add(friendNotificationItem)
        } else if (it.key.endsWith(NoticeType.friendApplyProcessed)) {
            //好友申请得到回应通知
            val noticeVOMap = it.value as Map<String, Any>
            val publishId = noticeVOMap["publishId"]
            val consumerId = noticeVOMap["consumerId"]
            val noticeType = noticeVOMap["noticeType"]
            val noticeVOData = noticeVOMap["data"] as Map<String, Any>
            val apply = noticeVOData["apply"] as Map<String, Any>
            val applyActiveId = apply["activeId"]
            val applyPassiveId = apply["passiveId"]
            val applyAuthenticationInformation = apply["authenticationInformation"]
            val applyIsGroup = apply["isGroup"]
            val applyId = apply["id"]
            val applyState = apply["state"]
            val passiveUserVo = noticeVOData["passiveUserVo"] as Map<String, Any>
            val account = passiveUserVo["account"]
            val username = passiveUserVo["username"]
            val age = passiveUserVo["age"]
            val sex = passiveUserVo["sex"]
            val email = passiveUserVo["email"]
            val phone = passiveUserVo["phone"]
            val creationTime = passiveUserVo["creationTime"]
            val updateTime = passiveUserVo["updateTime"]
            val avatar = passiveUserVo["avatar"]

            val friendNotificationItem = FriendNotificationItem(
                id = (applyId).toString().toLong(),
                headImage = avatar as String,
                userName = username as String,
                content = "验证信息：${applyAuthenticationInformation}",
                applyState = applyState as String,
                time = "2024/4/17",
                friendAccount = account as String,
                noticeType = NoticeType.friendApplyProcessed
            )
            //将通知保存本地数据库
            Db.saveFriendNotice(friendNotificationItem)
            homeViewModel?.friendNotificationItems?.add(friendNotificationItem)//更新通知列表UI
            if (friendNotificationItem.applyState == ApplyState.PASSED) {//如果同意了好友申请就保存好友信息
                val userVo = UserVo(
                    account = account.toString(),
                    username = username.toString(),
                    age = age.toString().toInt(),
                    sex = sex.toString(),
                    email = email.toString(),
                    phone = phone.toString(),
                    creationTime = creationTime.toString(),
                    updateTime = updateTime.toString(),
                    avatar = avatar.toString()
                )
                val friendsMappingItem = FriendsMappingItem(
                    account = userVo.account.toString(),
                    userName = userVo.username.toString(),
                    headUrl = userVo.avatar.toString(),
                    state = "[未知]",
                    personalSignature = "暂无个性签名",
                    userVo = userVo
                )
                Db.saveFriend(friendsMappingItem)//保存到数据库
                homeViewModel?.friendsMappingItems?.add(friendsMappingItem)//更新好友列表
                ChannelMappingRepository.channelMappingAccountList.add(friendsMappingItem.account)//更新好友列表
            }
        } else if (it.key.endsWith(NoticeType.groupCreate)) {
            val noticeVOMap = it.value as Map<String, Any>
            val noticeVOData = noticeVOMap["data"] as Map<String, Any>
            val groupVO = noticeVOData["groupVO"] as Map<String, Any>
            //更新UI
            val groupMappingItem = GroupMappingItem(
                id = IdUtil.getSnowflakeNextId(),
                groupHeadUrl = groupVO["groupAvatar"].toString(),
                groupName = groupVO["groupName"].toString(),
                groupAccount = groupVO["groupAccount"].toString()
            )
            homeViewModel?.groupMappingItems?.add(groupMappingItem)
            val groupNotificationItem = GroupNotificationItem(
                id = IdUtil.getSnowflakeNextId(),
                headImage = "",
                groupName = groupMappingItem.groupName,
                time = "2024/4/17",
                content = "群聊创建通知",
                noticeType = NoticeType.groupCreate,
                groupAccount = groupMappingItem.groupAccount
            )
            homeViewModel?.groupNotificationItems?.add(groupNotificationItem)
            //持久化
            Db.saveGroupNotice(groupNotificationItem)
            Db.saveGroup(groupMappingItem)
            val userVoList = groupVO["userVoList"] as List<JSONObject>
            userVoList.forEach { it1 ->
                val userVO=UserVo(
                    account = it1["account"] as String,
                    avatar = it1["avatar"] as String,
                    username = it1["username"] as String
                )
                Db.saveGroupUser(groupMappingItem.groupAccount, userVO)
            }
        }
    }
}

//解析JSON测试
fun main() {
    val response =
        "{\"type\":\"GET_MSG_RESPONSE\",\"data\":{\"notices\":{\"1779873389628997633groupCreate\":{\"publishId\":1779873389628997633,\"consumerId\":1779873389628997633,\"noticeType\":\"groupCreate\",\"date\":1714210450794,\"data\":{\"groupVO\":{\"id\":1784154060291620866,\"groupAccount\":\"1714210453486\",\"groupName\":\"weikjie、weikjie2等的群聊\",\"groupAvatar\":\"\",\"groupLeaderId\":1779873389628997633,\"userVoList\":[{\"account\":\"106387\",\"username\":\"weikjie\",\"age\":20,\"sex\":\"男\",\"email\":\"iwkj@foxmail.com\",\"phone\":\"19162027925\",\"creationTime\":\"2024-04-15 22:03:52\",\"updateTime\":\"2024-04-15 22:03:52\",\"avatar\":\"https://img0.baidu.com/it/u\\u003d3335297070,1036872951\\u0026fm\\u003d253\\u0026fmt\\u003dauto\\u0026app\\u003d138\\u0026f\\u003dJPEG?w\\u003d400\\u0026h\\u003d400\"},{\"account\":\"706750333\",\"username\":\"weikjie2\",\"age\":17,\"sex\":\"女\",\"email\":\"iwkj@foxmail.com\",\"phone\":\"18636567201\",\"creationTime\":\"2024-04-16 15:30:01\",\"updateTime\":\"2024-04-16 15:30:01\",\"avatar\":\"https://img2.baidu.com/it/u\\u003d2955738456,3500728517\\u0026fm\\u003d253\\u0026fmt\\u003dauto\\u0026app\\u003d138\\u0026f\\u003dJPEG?w\\u003d360\\u0026h\\u003d360\"}]}}}},\"messageVOList\":[]}}"
    val jsonObject: JSONObject = JSONUtil.parseObj(response)
    println("服务器响应：$response")
    val data: JSONObject = jsonObject["data"] as JSONObject
    val notices = data["notices"] as Map<String, Any>
    notices.forEach {
        if (it.key.endsWith(NoticeType.groupCreate)) {
            val noticeVOMap = it.value as Map<String, Any>
            val noticeVOData = noticeVOMap["data"] as Map<String, Any>
            val groupVO = noticeVOData["groupVO"] as Map<String, Any>
            //更新UI
            val groupMappingItem = GroupMappingItem(
                id = IdUtil.getSnowflakeNextId(),
                groupHeadUrl = groupVO["groupAvatar"].toString(),
                groupName = groupVO["groupName"].toString(),
                groupAccount = groupVO["groupAccount"].toString()
            )
            val groupNotificationItem = GroupNotificationItem(
                id = IdUtil.getSnowflakeNextId(),
                headImage = "",
                groupName = groupMappingItem.groupName,
                time = "2024/4/17",
                content = "群聊创建通知"
            )
            //持久化
            val userVoList = groupVO["userVoList"] as List<JSONObject>

        }

    }
}
